<?php
/**
 * CLasse ce chargent des formatages en XML
 * @author Jonathan Rotini
 * @version 0.7
 * @see Format
 * @todo complete the code
 */
final class FormatToXML extends Format
{
        public function __construct($data, Array $opt)
   {
     parent::__construc($data, $opt);
   }
        /**
         * Format un tableau au format HTML
         * Le paramètre option peut ne pas être précisé mais est utile pour préciser le nombre de caractère
         * d'une chaine de caractèrre racourcit par exemple.
         * @access public
         * @since 0.1
         * @return String
         * @todo peut être perfectionné grace a la gestion des options
         */
        public function format()
        {
                $this->_data = $data;
                $this->_opt = $opt;
                //On initialise le noeud principale de l'arbre
                if( isset($opt["root_elem"]) )
                {
                        $rootElement = $opt["root_elem"];
                }
                else
                {
                        $rootElement = "default";
                }
                $content = $this->_getOneLevelOfDOM( $this->_data, $rootElement);
                return $content;
        }
        /**
         * Fonction recurssive qui renvois un DOM sous forme de chaine de caractère a X niveau 
         * @access public
         * @since 0.1
         * @param Array $array
         * @param String $previous_node
         * @return string
         */
        private function _getOneLevelOfDOM($array, $previous_node)
        {
                $content = "";
                foreach( $array as $key => $val)
                {
                        $mane_node = (is_numeric($key))?substr($previous_node,0, strlen($previous_node)-1):$key;
                        $content .= "<".$mane_node.">";
                        if( is_array($val) )
                        {
                                $content .= $this->_getOneLevelOfDOM($val, $mane_node);
                        }
                        else
                        {
                                $content .= preg_replace("/(\r\n|\n|\r)/", "", str_replace("%", "&#37;", htmlspecialchars($val, ENT_QUOTES)));
                        }
                        $content .= "</".$mane_node.">";
                }
                return $content;
        }
  /************************************************************************************
   ************************************************************************************
   ************************************************************************************
   ***********************************************************************************/
   
  /**
         * Format de la donnée XML sous forme d'un array PHP manipulable
         * Le paramètre option peut ne pas être précisé mais est utile pour préciser le nombre de caractère
         * d'une chaine de caractèrre racourcit par exemple.
         * @access public
         * @since 2.2
         * @param XML $data
         * @param String $type
         * @param NULL $opt
         * @return String
         * @todo peut être perfectionné grace a la gestion des options
         */
        public function bis_format($data, $opt = array(), $null = NULL)
        {
                $xml = new DOMDocument();
                $array = array();
                if( $xml->loadXML($data) === FALSE )
                {
                        return false;
                }
                $root_node = $xml->documentElement->nodeName;
                $array[$root_node] = array();
                $array[$root_node] = $this->getDOM($xml->documentElement, $array[$root_node]);
                return $array;
        }
        /**
         * Fonction recurssive qui renvois un DOM a X niveau
         * @access public
         * @since 2.2
         * @param DOMElement $xml
         * @param Array $previous_node
         * @return Array
         * @todo do something for attributes, like ["name_node"]["node_attributes"]
         */
        private function getDOM($xml, $previous_node, $iterator = -2)
        { 
                /****
                 * On verifie le type de donné recus dans le premier argument.
                 * Si c'est un Array on itére dessus pour avoir un tableau avec indice numerique, sinon on considére que c'est un DOMElement
                 ****/
                if( is_array($xml) )
                {
                        foreach( $xml as $key => $node )
                        {
                                //On reste quand même dans une fonction recursive
                                $previous_node[$key] = $this->getDOM($node, array(), $iterator );
                        }
                        return $previous_node;
                }
                $childs = $xml->childNodes;
                unset($xml);
                $splitted_childs = $this->splitChilds( $childs );
                //On boucle sur tous les fils de l'elements
                foreach( $childs as $child )
                {
                        //Si c'est un node
                        if( $child instanceof DOMElement )
                        {
                                $node_name = $child->nodeName;
                                //Si c'est un noeud qui a des voisin de même nom on itére numériquement
                                if( isset($splitted_childs["iterate"][$child->nodeName]) )
                                {
                                        $child = $splitted_childs["iterate"][$child->nodeName];
                                }
                                $previous_node[$node_name] = null;
                                $previous_node[$node_name] = $this->getDOM($child, $previous_node[$node_name], $iterator );
                                unset( $node_name, $child);
                        }
                        //Si c'est juste du text
                        else if( $child instanceof DOMText )
                        {
                                //On verifie que ce n'est pas un element vide ( assez fréquent, surtout sur l'xml de google )
                                if( trim($child->wholeText) != "" )
                                {
                                        $previous_node = $child->wholeText;
                                }
                        }
                        //On réinitialise l'itérateur
                }
                unset($splitted_childs, $childs);
                return $previous_node;
        }
        /**
         * Sépare dans deux tableau différents les enfants qui on des voisins avec le même nom de noeud des autres
         * @access private
         * @since 2.2
         * @param DOMNodeList $childs
         * @return DOMNodeList[]
         */
        private function splitChilds( &$childs )
        {
                $array_nodeName = array();
                $array_iterate  = array();
                foreach( $childs as $child )
                {
                        if( $child instanceof DOMElement )
                        {
                                if( !array_key_exists($child->nodeName, $array_nodeName) )
                                {
                                        $array_nodeName[$child->nodeName] = $child;
                                }
                                else
                                {
                                        if( $array_nodeName[$child->nodeName] !== FALSE )
                                        {
                                                $array_iterate[$child->nodeName] = array();
                                                $array_iterate[$child->nodeName][] = $array_nodeName[$child->nodeName];
                                                $array_iterate[$child->nodeName][] = $child;
                                                $array_nodeName[$child->nodeName] = FALSE;
                                        }
                                        else
                                        {
                                                $array_iterate[$child->nodeName][] = $child;
                                        }
                                }
                        }
                }
                return array("nodeName" => $array_nodeName, "iterate" => $array_iterate);
        }
   
}
?>
